home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!sun-barr!ames!pasteur!nntp
- From: scott.oaks@East.Sun.COM (Scott Oaks)
- Newsgroups: comp.sources.x
- Subject: v15i162: OpenLook Virtual Window Mgr (3.0), Part16/21
- Message-ID: <1992Feb4.135937.8021@pasteur.Berkeley.EDU>
- Date: 4 Feb 92 13:59:37 GMT
- References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
- Sender: dcmartin@msi.com (David C. Martin - Moderator)
- Organization: University of California, at Berkeley
- Lines: 1990
- Approved: dcmartin@msi.com
- Nntp-Posting-Host: postgres.berkeley.edu
-
- Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
- Posting-number: Volume 15, Issue 162
- Archive-name: olvwm-3.0/part16
-
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 16 (of 21)."
- # Contents: LEGAL_NOTICE events.c slots.c wingframe.c
- # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:47 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'LEGAL_NOTICE' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'LEGAL_NOTICE'\"
- else
- echo shar: Extracting \"'LEGAL_NOTICE'\" \(2808 characters\)
- sed "s/^X//" >'LEGAL_NOTICE' <<'END_OF_FILE'
- X NOTICE TO USER: The source code, including the glyphs or icons
- X forming a par of the OPEN LOOK TM Graphic User Interface, on this
- X tape and in these files is copyrighted under U.S. and international
- X laws. Sun Microsystems, Inc. of Mountain View, California owns
- X the copyright and has design patents pending on many of the icons.
- X AT&T is the owner of the OPEN LOOK trademark associated with the
- X materials on this tape. Users and possessors of this source code
- X are hereby granted a nonexclusive, royalty-free copyright and
- X design patent license to use this code in individual and
- X commercial software. A royalty-free, nonexclusive trademark
- X license to refer to the code and output as "OPEN LOOK" compatible
- X is available from AT&T if, and only if, the appearance of the
- X icons or glyphs is not changed in any manner except as absolutely
- X necessary to accommodate the standard resolution of the screen or
- X other output device, the code and output is not changed except as
- X authorized herein, and the code and output is validated by AT&T.
- X Bigelow & Holmes is the owner of the Lucida (R) trademark for the
- X fonts and bit-mapped images associated with the materials on this
- X tape. Users are granted a royalty-free, nonexclusive license to use
- X the trademark only to identify the fonts and bit-mapped images if,
- X and only if, the fonts and bit-mapped images are not modified in any
- X way by the user.
- X
- X
- X Any use of this source code must include, in the user documentation
- X and internal comments to the code, notices to the end user as
- X follows:
- X
- X
- X (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
- X pending in the U.S. and foreign countries. OPEN LOOK is a
- X trademark of AT&T. Used by written permission of the owners.
- X
- X
- X (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered
- X trademark of Bigelow & Holmes. Permission to use the Lucida
- X trademark is hereby granted only in association with the images
- X and fonts described in this file.
- X
- X
- X
- X SUN MICROSYSTEMS, INC., AT&T, AND BIGELOW & HOLMES
- X MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF
- X THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
- X WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.
- X SUN MICROSYSTEMS, INC., AT&T AND BIGELOW & HOLMES,
- X SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES
- X WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED
- X WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- X PARTICULAR PURPOSE. IN NO EVENT SHALL SUN MICROSYSTEMS,
- X INC., AT&T OR BIGELOW & HOLMES BE LIABLE FOR ANY
- X SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
- X OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
- X OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- X OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- X WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
- END_OF_FILE
- if test 2808 -ne `wc -c <'LEGAL_NOTICE'`; then
- echo shar: \"'LEGAL_NOTICE'\" unpacked with wrong size!
- fi
- # end of 'LEGAL_NOTICE'
- fi
- if test -f 'events.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'events.c'\"
- else
- echo shar: Extracting \"'events.c'\" \(16710 characters\)
- sed "s/^X//" >'events.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
- X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
- X * file for terms of the license.
- X */
- X
- X#ident "@(#)events.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)events.c 26.40 91/09/14 SMI"
- X *
- X */
- X
- X#include <errno.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X
- X#include <X11/Xlib.h>
- X#include <X11/Xresource.h>
- X#include <X11/Xutil.h>
- X#include <X11/keysym.h>
- X
- X#include "i18n.h"
- X#include "ollocale.h"
- X#include "olwm.h"
- X#include "win.h"
- X#include "globals.h"
- X#include "events.h"
- X#include "list.h"
- X#include "mem.h"
- X
- X/* ===== externs ========================================================== */
- X
- Xextern int DeadChildren;
- Xextern void ReapChildren();
- X
- X/* ===== globals ========================================================== */
- X
- XTime LastEventTime = (Time) 0;
- XKeySym *KbdMap = NULL; /* pointer to current key table; 2d array */
- Xint MinKeyCode = 0;
- Xint MaxKeyCode = 0;
- Xint KeySymsPerKeyCode = 0;
- X
- X/* ===== private data ===================================================== */
- X
- Xstatic int (*interposer)() = NULL;
- Xstatic void *closure;
- Xstatic List *deferredEventListHead = NULL_LIST;
- Xstatic List *deferredEventListTail = NULL_LIST;
- X
- Xstatic struct timeval timeoutNext = {0, 0};
- Xstatic TimeoutFunc timeoutFunc = NULL;
- Xstatic void *timeoutClosure = NULL;
- X
- Xstatic XModifierKeymap *ModMap = NULL;
- X
- Xstatic explicitPointerGrab = False;
- X
- X/* ===== private functions ================================================ */
- X
- X/*
- X * lookupWindow
- X *
- X * Given an event, look up the WinInfo corresponding to the window field of
- X * the event. For events that have no window field, return NULL.
- X */
- XWinGeneric *
- XlookupWindow( event )
- X XEvent *event;
- X{
- X switch ( event->xany.type ) {
- X case KeymapNotify:
- X case MappingNotify:
- X /* these events have no window field */
- X return NULL;
- X default:
- X return WIGetInfo( event->xany.window );
- X }
- X}
- X
- X
- X/*
- X * saveTimestamp
- X *
- X * Given an event, update LastEventTime with its timestamp. For events that
- X * have no timestamp, do nothing.
- X */
- Xvoid
- XsaveTimestamp( event )
- X XEvent *event;
- X{
- X switch ( event->xany.type ) {
- X case KeyPress:
- X case KeyRelease:
- X LastEventTime = event->xkey.time;
- X break;
- X case ButtonPress:
- X case ButtonRelease:
- X LastEventTime = event->xbutton.time;
- X break;
- X case MotionNotify:
- X LastEventTime = event->xmotion.time;
- X break;
- X case EnterNotify:
- X case LeaveNotify:
- X LastEventTime = event->xcrossing.time;
- X break;
- X case PropertyNotify:
- X LastEventTime = event->xproperty.time;
- X break;
- X case SelectionClear:
- X LastEventTime = event->xselectionclear.time;
- X break;
- X case SelectionRequest:
- X /*
- X * The timestamp in SelectionRequest events comes from other clients;
- X * it's not generated by the server. It's thus not clear whether we
- X * should believe any timestamp in one of these events.
- X */
- X /* LastEventTime = event->xselectionrequest.time; */
- X break;
- X case SelectionNotify:
- X /*
- X * Ignore SelectionNotify events generated by other clients.
- X * Save only the timestamps from server-generated events.
- X */
- X if (!event->xany.send_event)
- X LastEventTime = event->xselection.time;
- X break;
- X default:
- X break;
- X }
- X}
- X
- X
- X/*
- X * Dispatches an event normally (i.e. not through an interposer). Looks up
- X * the window structure from the event's window ID and calls the appropriate
- X * event function for that window's class. All extension events are handled
- X * through a single extension event handler in the class. If explicitGrab is
- X * set, then someone has explicitly grabbed the pointer and redispatched the
- X * event to a handler that is expecting an implicit grab, and so which won't
- X * ungrab the pointer. We must therefore do an explicit ungrab of the
- X * pointer.
- X */
- Xstatic void
- XdispatchEvent(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinGeneric *winInfo;
- X{
- X EvFunc evFunc;
- X
- X if (GRV.PrintAll)
- X DebugEvent(event, "Dispatch - debug");
- X
- X saveTimestamp( event );
- X
- X if (winInfo == NULL)
- X {
- X if (DispatchVirtual(dpy, event))
- X return;
- X else {
- X /* REMIND should we do anything with these events? */
- X if (GRV.PrintOrphans)
- X DebugEvent(event, "Orphaned (null window)");
- X
- X /* If a client unmaps and then remaps its window, the
- X * MapRequest comes in on the frame window, but we just
- X * destroyed that window (on the unmap) so it appears as
- X * an orphan window. Hence we'll just create a new
- X * frame/etc via StateNew()
- X */
- X if (event->xany.type == MapRequest) {
- X StateNew(dpy, None,
- X event->xmaprequest.window, False, NULL);
- X }
- X }
- X
- X return;
- X }
- X
- X if (GRV.PrintAll)
- X DebugWindow(winInfo);
- X
- X#ifdef DEBUG
- X if (winInfo->class == NULL)
- X {
- X ErrorGeneral("Window instance with NULL class pointer");
- X }
- X
- X if (winInfo->core.kind != winInfo->class->core.kind)
- X ErrorWarning("Warning: window with kind different than class kind");
- X#endif
- X
- X if (event->xany.type >= LASTEvent)
- X evFunc = WinClass(winInfo)->core.extEventHdlr;
- X else
- X evFunc = WinClass(winInfo)->core.xevents[event->xany.type];
- X
- X if (evFunc != NULL)
- X {
- X (*evFunc)(dpy, event, winInfo);
- X }
- X else if (!DispatchVirtual(dpy, event))
- X if (GRV.PrintOrphans)
- X DebugEvent(event, "Orphaned");
- X
- X if (explicitPointerGrab && event->type == ButtonRelease &&
- X AllButtonsUp(event))
- X {
- X XUngrabPointer(dpy, event->xbutton.time);
- X }
- X}
- X
- Xstatic int
- XdispatchInterposer(dpy, event)
- XDisplay *dpy;
- XXEvent *event;
- X{
- X int disposition;
- X WinGeneric *winInfo;
- X XEvent *temp;
- X
- X if (GRV.PrintAll)
- X DebugEvent(event, "Dispatch - interposer");
- X
- X saveTimestamp( event );
- X winInfo = lookupWindow(event);
- X disposition = (*interposer)(dpy, event, winInfo, closure);
- X
- X switch (disposition) {
- X case DISPOSE_DISPATCH:
- X dispatchEvent(dpy, event, winInfo);
- X break;
- X case DISPOSE_DEFER:
- X temp = MemNew(XEvent);
- X *temp = *event;
- X if (deferredEventListHead == NULL_LIST) {
- X deferredEventListHead = ListCons(temp, NULL_LIST);
- X deferredEventListTail = deferredEventListHead;
- X } else {
- X deferredEventListTail->next = ListCons(temp, NULL_LIST);
- X deferredEventListTail = deferredEventListTail->next;
- X }
- X break;
- X case DISPOSE_USED:
- X /* do nothing */
- X break;
- X }
- X}
- X
- Xstatic void
- XdoTimeout()
- X{
- X TimeoutFunc f;
- X void *closure;
- X
- X f = timeoutFunc;
- X closure = timeoutClosure;
- X TimeoutCancel();
- X (*f)(closure);
- X}
- X
- Xstatic void
- XnextEventOrTimeout(dpy, event)
- XDisplay *dpy;
- XXEvent *event;
- X{
- X int fd = ConnectionNumber(dpy);
- X struct timeval polltime;
- X fd_set rdset, wrset, xset;
- X int ready = -1;
- X
- X while (XPending(dpy) == 0 && ready <= 0 && timeoutFunc != NULL) {
- X gettimeofday(&polltime,NULL);
- X if ((timeoutFunc != NULL) &&
- X ((polltime.tv_sec > timeoutNext.tv_sec) ||
- X ((polltime.tv_sec == timeoutNext.tv_sec) &&
- X (polltime.tv_usec >= timeoutNext.tv_usec))))
- X {
- X doTimeout();
- X continue;
- X }
- X
- X polltime.tv_sec = timeoutNext.tv_sec - polltime.tv_sec;
- X polltime.tv_usec = 0;
- X
- X FD_ZERO(&rdset);
- X FD_SET(fd,&rdset);
- X FD_ZERO(&wrset);
- X FD_ZERO(&xset);
- X FD_SET(fd,&xset);
- X
- X ready = select(fd+1,&rdset,&wrset,&xset,&polltime);
- X
- X gettimeofday(&polltime,NULL);
- X if ((timeoutFunc != NULL) &&
- X ((polltime.tv_sec > timeoutNext.tv_sec) ||
- X ((polltime.tv_sec == timeoutNext.tv_sec) &&
- X (polltime.tv_usec >= timeoutNext.tv_usec))))
- X {
- X doTimeout();
- X }
- X }
- X
- X XNextEvent(dpy, event);
- X}
- X
- X
- X/*
- X * Update our own modifier map. This is unfortunate, as we know Xlib already
- X * keeps this information around.
- X */
- Xstatic void
- XupdateModifierMap(dpy)
- X Display *dpy;
- X{
- X if (ModMap != NULL)
- X XFreeModifiermap(ModMap);
- X ModMap = XGetModifierMapping(dpy);
- X}
- X
- X
- X/*
- X * Update our own keyboard table. This is unfortunate, as we know Xlib
- X * already keeps this information around.
- X */
- Xstatic void
- XupdateKeyboardMap(dpy)
- X Display *dpy;
- X{
- X if (KbdMap != NULL )
- X XFree((char *)KbdMap);
- X XDisplayKeycodes(dpy, &MinKeyCode, &MaxKeyCode);
- X KbdMap = XGetKeyboardMapping(dpy, MinKeyCode, MaxKeyCode-MinKeyCode+1,
- X &KeySymsPerKeyCode);
- X}
- X
- X
- X/*
- X * Handle MappingNotify events. Refresh cached information about the keyboard
- X * and the pointer.
- X */
- Xvoid
- XhandleMappingNotify(dpy, e)
- X Display *dpy;
- X XEvent *e;
- X{
- X XMappingEvent *mapEvent = (XMappingEvent *)e;
- X
- X switch (mapEvent->request) {
- X case MappingModifier:
- X XRefreshKeyboardMapping(mapEvent);
- X updateModifierMap(dpy);
- X RefreshKeyGrabs(dpy);
- X RefreshButtonGrabs(dpy);
- X break;
- X case MappingKeyboard:
- X XRefreshKeyboardMapping(mapEvent);
- X updateKeyboardMap(dpy);
- X RefreshKeyGrabs(dpy);
- X break;
- X case MappingPointer:
- X /* no need to handle pointer mapping changes */
- X break;
- X }
- X}
- X
- X
- X/*ARGSUSED*/
- Xstatic void *
- XredispatchEvent(e,c)
- X XEvent *e;
- X void *c;
- X{
- X dispatchEvent(e->xany.display, e, lookupWindow(e));
- X MemFree(e);
- X return (void *)NULL;
- X}
- X
- X
- X/*
- X * Compute t2 - t1 and return the time value in diff. The tv_usec field is
- X * always in the range 0..999999. This means that negative time values always
- X * have tv_sec less than zero. For instance, negative one-half seconds is
- X * represented with tv_sec == -1 and tv_usec == 500000.
- X */
- Xstatic void
- Xtvdiff(t1, t2, diff)
- X struct timeval *t1, *t2, *diff;
- X{
- X diff->tv_sec = t2->tv_sec - t1->tv_sec;
- X diff->tv_usec = t2->tv_usec - t1->tv_usec;
- X if (diff->tv_usec < 0) {
- X diff->tv_sec -= 1;
- X diff->tv_usec += 1000000;
- X }
- X}
- X
- X
- X/* ===== public functions ================================================= */
- X
- X
- X/*
- X * EventLoop
- X *
- X * The main event loop. Reads events from the wire and dispatches them.
- X */
- Xvoid
- XEventLoop( dpy )
- X Display *dpy;
- X{
- X XEvent event;
- X
- X for (;;) {
- X if (timeoutFunc == NULL)
- X {
- X XNextEvent( dpy, &event );
- X }
- X else
- X {
- X nextEventOrTimeout(dpy, &event);
- X }
- X
- X if (DeadChildren > 0)
- X ReapChildren();
- X
- X /*
- X * Discard user events that have the Synthetic bit set.
- X *
- X * All device events (mouse and keyboard events) have types
- X * that fall in between KeyPress and MotionNotify.
- X */
- X if (event.xany.send_event
- X && event.type <= MotionNotify
- X && event.type >= KeyPress)
- X continue;
- X
- X
- X /*
- X * Handle MappingNotify events. These events don't have
- X * window field, so they can't be dispatched normally.
- X */
- X if (event.xany.type == MappingNotify) {
- X handleMappingNotify(dpy, &event);
- X continue;
- X }
- X
- X /*
- X * If there is an event interposer, and it returns True, that
- X * means it has successfully processed the event. We continue
- X * around the loop instead of processing the event normally.
- X */
- X if ( interposer != NULL)
- X dispatchInterposer(dpy, &event);
- X else
- X dispatchEvent(dpy, &event, lookupWindow(&event));
- X }
- X
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * Propagate an event to this window's parent. REMIND: doesn't update the
- X * event fields or the event coordinates.
- X */
- Xint
- XPropagateEventToParent(dpy,event,win)
- XDisplay *dpy;
- XXEvent *event;
- XWinGeneric *win;
- X{
- X dispatchEvent(dpy,event,win->core.parent);
- X}
- X
- X
- X/*
- X * Propagate a ButtonPress event to a child window. Win is assumed to be a
- X * child of the event window. The event window and subwindow fields are
- X * updated, and the coordinates are translated to the child's coordinate
- X * system. Sets the explicitPointerGrab flag.
- X */
- Xvoid
- XPropagatePressEventToChild(dpy, event, win)
- X Display *dpy;
- X XButtonPressedEvent *event;
- X WinGeneric *win;
- X{
- X event->window = win->core.self;
- X event->subwindow = None;
- X event->x -= win->core.x;
- X event->y -= win->core.y;
- X dispatchEvent(dpy, event, win);
- X explicitPointerGrab = True;
- X}
- X
- X
- X/*
- X * FindModifierMask
- X *
- X * Given a keycode, look in the modifier mapping table to see if this keycode
- X * is a modifier. If it is, return the modifier mask bit for this key;
- X * otherwise, return zero.
- X */
- Xunsigned int
- XFindModifierMask(kc)
- XKeyCode kc;
- X{
- X int i, j;
- X KeyCode *mapentry;
- X
- X if (ModMap == NULL || kc == 0)
- X return 0;
- X
- X mapentry = ModMap->modifiermap;
- X for (i=0; i<8; ++i) {
- X for (j=0; j<(ModMap->max_keypermod); ++j) {
- X if (kc == *mapentry)
- X return 1 <<
- X ( (mapentry - ModMap->modifiermap) /
- X ModMap->max_keypermod );
- X ++mapentry;
- X }
- X }
- X return 0;
- X}
- X
- X
- X/*
- X * Wait on dpy for some events to come in or for a timeout to occur. If
- X * events come in, return True and change timeout to indicate the amount of
- X * time remaining. If no events come in before the timeout expires, return
- X * False. A negative timestamp is considered to have timed out immediately.
- X */
- XBool
- XAwaitEvents(dpy, timeout)
- X Display *dpy;
- X struct timeval *timeout;
- X{
- X struct timeval starttime, curtime, diff1, diff2;
- X fd_set rfds;
- X int s;
- X
- X if (timeout->tv_sec < 0)
- X return False;
- X
- X (void) gettimeofday(&starttime, NULL);
- X
- X while (1) {
- X FD_ZERO(&rfds);
- X FD_SET(ConnectionNumber(dpy), &rfds);
- X s = select(ConnectionNumber(dpy)+1, &rfds, NULL, NULL, timeout);
- X if (s == 0) {
- X /* we timed out without getting anything */
- X return False;
- X }
- X
- X /*
- X * If an error occurred, report it and return False.
- X */
- X if (s == -1 && errno != EINTR) {
- X perror("select");
- X#ifdef DEBUG
- X fputs("olvwm: generating core dump for analysis...\n", stderr);
- X if (fork() == 0) {
- X abort();
- X exit(1);
- X }
- X#endif
- X return False;
- X }
- X
- X /*
- X * Either we got interrupted or the descriptor became ready, or both.
- X * Compute the remaining time on the timeout. This can be negative,
- X * because there is a slight window for delays between the select()
- X * call above and this gettimeofday() call. This means that we can
- X * return an indication of valid data to the caller, yet also return
- X * a value for the time remaining that is less than or equal to zero.
- X */
- X (void) gettimeofday(&curtime, NULL);
- X tvdiff(&starttime, &curtime, &diff1);
- X tvdiff(&diff1, timeout, &diff2);
- X *timeout = diff2;
- X starttime = curtime;
- X
- X /*
- X * If we got some data, return True. Otherwise, we were interrupted.
- X * If we timed out, return False. If not, there is time remaining;
- X * continue around the loop.
- X */
- X if (s > 0)
- X return True;
- X
- X if (timeout->tv_sec < 0)
- X return False;
- X }
- X}
- X
- X
- X/***************************************************************************
- X* Interposer functions
- X***************************************************************************/
- X
- X/*
- X * InstallInterposer
- X *
- X * Install an event interposition function. Nested interposition is illegal.
- X */
- Xvoid
- XInstallInterposer( func, cl )
- X Bool (*func)();
- X void *cl;
- X{
- X if ( interposer != NULL ) {
- X fputs( gettext("olvwm: warning, nested event interposer!\n"), stderr );
- X#ifdef DEBUG
- X abort();
- X#endif /* DEBUG */
- X }
- X interposer = func;
- X closure = cl;
- X}
- X
- X/*
- X * UninstallInterposer
- X *
- X * Uninstalls an event interposition function. Does nothing if there is
- X * currently no interposer. Replays any queued events. Inhibits focus
- X * changes and colormap installation while replaying them. This prevents
- X * redundant focus changes and colormap installation.
- X */
- Xvoid
- XUninstallInterposer()
- X{
- X interposer = (int (*)()) NULL;
- X
- X if (deferredEventListHead != NULL) {
- X ClientInhibitFocus(True);
- X ColormapInhibit(True);
- X ListApply(deferredEventListHead, redispatchEvent, 0);
- X ListDestroy(deferredEventListHead);
- X deferredEventListHead = deferredEventListTail = NULL_LIST;
- X ClientInhibitFocus(False);
- X ColormapInhibit(False);
- X }
- X}
- X
- X
- X/*
- X * Return an indication of whether an interposer is currently installed.
- X */
- XBool
- XInterposerInstalled()
- X{
- X return (interposer != NULL) ? True : False;
- X}
- X
- X
- X/***************************************************************************
- X* Timeout functions
- X***************************************************************************/
- X
- X/* TimeoutRequest(t,f,c) -- request that a timeout be generated t microseconds
- X * in the future; when the timeout occurs, the function f is called
- X * with the closure c.
- X */
- Xvoid
- XTimeoutRequest(t,f,c)
- Xint t;
- XTimeoutFunc f;
- Xvoid *c;
- X{
- X#ifdef DEBUG
- X if (timeoutFunc != NULL)
- X {
- X ErrorWarning("Timeout being set while another timeout current");
- X }
- X#endif
- X gettimeofday(&timeoutNext,NULL);
- X timeoutNext.tv_sec += t / 1000000;
- X timeoutNext.tv_usec += t % 1000000;
- X if (timeoutNext.tv_usec >= 1000000) {
- X timeoutNext.tv_usec -= 1000000;
- X timeoutNext.tv_sec += 1;
- X }
- X timeoutFunc = f;
- X timeoutClosure = c;
- X}
- X
- X/* TimeoutCancel() -- cancel an outstanding timeout.
- X */
- Xvoid
- XTimeoutCancel()
- X{
- X timeoutNext.tv_sec = 0;
- X timeoutNext.tv_usec = 0;
- X timeoutFunc = NULL;
- X timeoutClosure = NULL;
- X}
- X
- X
- X/*
- X * Initialize the event handling system. This function is called exactly
- X * once at startup.
- X */
- Xvoid
- XInitEvents(dpy)
- X Display *dpy;
- X{
- X updateKeyboardMap(dpy);
- X updateModifierMap(dpy);
- X}
- END_OF_FILE
- if test 16710 -ne `wc -c <'events.c'`; then
- echo shar: \"'events.c'\" unpacked with wrong size!
- fi
- # end of 'events.c'
- fi
- if test -f 'slots.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'slots.c'\"
- else
- echo shar: Extracting \"'slots.c'\" \(16468 characters\)
- sed "s/^X//" >'slots.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990 Sun Microsystems, Inc. Sun design patents
- X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
- X * file for terms of the license.
- X */
- X
- X#ident "@(#)slots.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)slots.c 26.8 91/09/14 SMI"
- X *
- X */
- X
- X#include <stdio.h>
- X#include <X11/Xos.h>
- X#include <X11/Xlib.h>
- X#include <X11/Xutil.h>
- X
- X#include "i18n.h"
- X#include "ollocale.h"
- X#include "mem.h"
- X#include "st.h"
- X#include "olwm.h"
- X#include "win.h"
- X#include "globals.h"
- X#include "list.h"
- X#include "slots.h"
- X
- X#define PLUSINFINITY 0xfffffff /* REMIND fix this for architecture-independence */
- X
- X/***************************************************************************
- X* Local functions
- X***************************************************************************/
- X
- X#define ROUNDUP(n,d) (((n)+(d)-1)/(d))
- X/* #define ROUND(n,d) ((0.5+((float)(n)/(float)(d)))*(int)(d)) */
- X#define ROUND(n,d) (((((n)%(d))>((d)/2))?(((n)/(d))+1):((n)/(d)))*(d))
- X
- X#define SLOTOFFSET(ig,ma,mi) (((ma))*(ig)->mislots+(mi))
- X#define AOCCUPANCY(ig,ma,mi) ((ig->occupancy+SLOTOFFSET((ig),(ma),(mi))))
- X#define OCCUPANCY(ig,ma,mi) (*(AOCCUPANCY((ig),(ma),(mi))))
- X
- X#define ISVERT(so) (((so)==SOBottomToTop)||((so)==SOTopToBottom))
- X#define ISHORZ(so) (((so)==SOLeftToRight)||((so)==SORightToLeft))
- X#define ISDECREASING(so) (((so)==SORightToLeft)||((so)==SOBottomToTop))
- X
- Xstatic char *
- Xsotochar(so)
- XSlotOrder so;
- X{
- X if (so == SOTopToBottom)
- X return ("SOTopToBottom");
- X if (so == SOBottomToTop)
- X return ("SOBottomToTop");
- X if (so == SOLeftToRight)
- X return ("SOLeftToRight");
- X if (so == SORightToLeft)
- X return ("SORightToLeft");
- X return("SOIllegal");
- X}
- X
- X#ifdef notused
- X#ifdef DEBUG
- X/* dumpocc -- print the occupancy count table to stderr
- X */
- Xstatic void
- Xdumpocc()
- X{
- X int ima, imi;
- X
- X fprintf(stderr,"dump of occupancy table:\n");
- X for (ima = 0; ima<maslots; ima++)
- X for (imi = 0; imi<mislots; imi++)
- X if (OCCUPANCY(ima,imi)!=0)
- X fprintf(stderr,"%x: occ[%d,%d]/[%d] = %d\n",AOCCUPANCY(ima,imi),ima,imi,SLOTOFFSET(ima,imi),OCCUPANCY(ima,imi));
- X fprintf(stderr,"end of dump of occupancy table\n");
- X}
- X#endif
- X#endif
- X
- X
- X/* setMajorMinor -- set two output variables from two input variables,
- X * based on the major/minor settings.
- X */
- Xstatic void
- XsetMajorMinor(iconGrid,r,c,pma,pmi)
- XIconGrid *iconGrid;
- Xint r, c, *pma, *pmi;
- X{
- X if (ISVERT(iconGrid->SOmajor))
- X {
- X *pma = r;
- X *pmi = c;
- X }
- X else
- X {
- X *pma = c;
- X *pmi = r;
- X }
- X}
- X
- X/* setAbsolute -- set two output variables from two input variables, based
- X * on major/minor settings; this is the inverse of setMajorMinor.
- X */
- Xstatic void
- XsetAbsolute(iconGrid,ma,mi,pr,pc)
- XIconGrid *iconGrid;
- Xint ma, mi;
- Xint *pr, *pc;
- X{
- X if (ISVERT(iconGrid->SOmajor))
- X {
- X *pr = ma;
- X *pc = mi;
- X }
- X else
- X {
- X *pc = ma;
- X *pr = mi;
- X }
- X}
- X
- X/* incrRegion -- increment the occupancy count of a region
- X */
- Xstatic void
- XincrRegion(iconGrid,slot,val)
- XIconGrid *iconGrid;
- XIconSlot *slot;
- Xint val;
- X{
- X int ii,jj;
- X
- X for (ii = slot->ma;
- X (ii>=0)&&(ii<iconGrid->maslots)&&(ii<slot->ma+slot->maw); ii++)
- X for (jj = slot->mi;
- X (jj>=0)&&(jj<iconGrid->mislots)&&(jj<slot->mi+slot->miw); jj++)
- X {
- X if ((OCCUPANCY(iconGrid,ii,jj) += val) < iconGrid->minoccupancy)
- X iconGrid->minoccupancy = OCCUPANCY(iconGrid,ii,jj);
- X }
- X}
- X
- X/* findMinMaxRgn -- find the minimum and maximum occupancies of a region
- X */
- Xstatic void
- XfindMinMaxRgn(iconGrid,ma, mi, nmajor, nminor, pminrgn, pmaxrgn)
- XIconGrid *iconGrid;
- Xint ma, mi, nmajor, nminor, *pminrgn, *pmaxrgn;
- X{
- X int min, max;
- X int ii, jj;
- X int occ;
- X
- X min = PLUSINFINITY;
- X max = -1;
- X
- X for (ii=ma; ii<ma+nmajor; ii++)
- X for (jj = mi; jj<mi+nminor; jj++)
- X {
- X occ = OCCUPANCY(iconGrid,ii,jj);
- X if (occ < min)
- X min = occ;
- X if (occ > max)
- X max = occ;
- X }
- X *pminrgn = min;
- X *pmaxrgn = max;
- X}
- X
- Xstatic IconSlot *
- XincrDynamicSlots(iconGrid,nmajor, nminor)
- XIconGrid *iconGrid;
- Xint nmajor, nminor;
- X{
- X int minoccrgn; /* smallest occupancy found for a region of given size */
- X int minfound, minfoundrgn; /* smallest occupancy found for one slot
- X * and a region respectively; used to reset
- X * search values */
- X int ma, mi; /* indices in major and minor directions */
- X int maxrgn, minrgn; /* max and min occupancies in a region */
- X IconSlot *slot = MemNew(IconSlot);
- X
- X minoccrgn = iconGrid->minoccupancy;
- X slot->positioned = False;
- X
- X for (;;) /* will actually only iterate twice */
- X {
- X minfound = minfoundrgn = PLUSINFINITY;
- X for (ma = 0; (ma <= iconGrid->maslots-nmajor); ma++)
- X {
- X for (mi = 0; (mi <= iconGrid->mislots-nminor); mi++)
- X {
- X findMinMaxRgn(iconGrid,ma,mi,nmajor,nminor,&minrgn,&maxrgn);
- X if (minrgn < minfound)
- X minfound = minrgn;
- X if (maxrgn < minfoundrgn)
- X minfoundrgn = maxrgn;
- X if (maxrgn <= minoccrgn)
- X {
- X slot->ma = ma;
- X slot->mi = mi;
- X slot->maw = nmajor;
- X slot->miw = nminor;
- X incrRegion(iconGrid,slot,1);
- X return slot;
- X }
- X }
- X }
- X /* no regions available with occupancy <= known minimum */
- X if (minfound > iconGrid->minoccupancy) /* increase slot minimum */
- X iconGrid->minoccupancy = minfound;
- X minoccrgn = minfoundrgn; /* increase local region min */
- X }
- X}
- X
- X/* setIconPos -- given a slot, position the icon frame window accordingly.
- X */
- Xstatic void
- XsetIconPos(win, slot)
- XWinIconFrame *win;
- XIconSlot *slot;
- X{
- X int x,y;
- X IconGrid *iconGrid = win->core.client->scrInfo->iconGrid;
- X
- X if (iconGrid->SOmajor == SOTopToBottom)
- X {
- X y = ICON_GRID_HEIGHT*slot->ma;
- X if (iconGrid->SOminor == SOLeftToRight)
- X {
- X x = ICON_GRID_WIDTH*slot->mi;
- X }
- X else
- X {
- X x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
- X }
- X }
- X else if (iconGrid->SOmajor == SOBottomToTop)
- X {
- X y = iconGrid->pixvert - ICON_GRID_HEIGHT*slot->ma - win->core.height;
- X if (iconGrid->SOminor == SOLeftToRight)
- X {
- X x = ICON_GRID_WIDTH*slot->mi;
- X }
- X else
- X {
- X x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
- X }
- X }
- X else if (iconGrid->SOmajor == SOLeftToRight)
- X {
- X x = ICON_GRID_WIDTH*slot->ma;
- X if (iconGrid->SOminor == SOTopToBottom)
- X {
- X y = ICON_GRID_HEIGHT*slot->mi;
- X }
- X else
- X {
- X y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
- X }
- X }
- X else if (iconGrid->SOmajor == SORightToLeft)
- X {
- X x = iconGrid->pixhoriz - ICON_GRID_WIDTH*slot->ma - win->core.width;
- X if (iconGrid->SOminor == SOTopToBottom)
- X {
- X y = ICON_GRID_HEIGHT*slot->mi;
- X }
- X else
- X {
- X y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
- X }
- X }
- X
- X x += slot->off_x;
- X y += slot->off_y;
- X (WinFunc(win,core.newposfunc))(win, x, y);
- X}
- X
- X/* incrPositionedSlots -- an icon has been explicitly positioned; create an
- X * iconslot record and increment the occupancy count of the affected slots.
- X */
- Xstatic IconSlot *
- XincrPositionedSlots(iconGrid,x,y,w,h,snaptogrid)
- XIconGrid *iconGrid;
- Xint x,y,w,h;
- XBool snaptogrid;
- X{
- X IconSlot *slot = MemNew(IconSlot);
- X#define ROUNDIF(v,w) (snaptogrid?ROUND((v),(w)):(v))/(w)
- X#define ROUNDDIM(p,s,w) (ROUNDUP(((p)%(w))+(s),(w)))
- X
- X if (iconGrid->SOmajor == SOTopToBottom)
- X {
- X slot->ma = ROUNDIF(y,ICON_GRID_HEIGHT);
- X slot->maw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
- X if (iconGrid->SOminor == SOLeftToRight)
- X {
- X slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
- X slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
- X }
- X else
- X {
- X slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
- X slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
- X }
- X }
- X else if (iconGrid->SOmajor == SOBottomToTop)
- X {
- X slot->ma = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
- X slot->maw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
- X slot->miw = w;
- X if (iconGrid->SOminor == SOLeftToRight)
- X {
- X slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
- X slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
- X }
- X else
- X {
- X slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
- X slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
- X }
- X }
- X else if (iconGrid->SOmajor == SOLeftToRight)
- X {
- X slot->ma = ROUNDIF(x,ICON_GRID_WIDTH);
- X slot->maw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
- X if (iconGrid->SOminor == SOTopToBottom)
- X {
- X slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
- X slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
- X }
- X else
- X {
- X slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
- X slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
- X }
- X }
- X else if (iconGrid->SOmajor == SORightToLeft)
- X {
- X slot->ma = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
- X slot->maw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
- X if (iconGrid->SOminor == SOTopToBottom)
- X {
- X slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
- X slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
- X }
- X else
- X {
- X slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
- X slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
- X }
- X }
- X if (slot->ma < 0) slot->ma = 0;
- X if (slot->ma >= iconGrid->maslots) slot->ma = iconGrid->maslots-1;
- X if (slot->mi < 0) slot->mi = 0;
- X if (slot->mi >= iconGrid->mislots) slot->mi = iconGrid->mislots-1;
- X slot->positioned = True;
- X incrRegion(iconGrid,slot,1);
- X return slot;
- X}
- X
- X
- X/***************************************************************************
- X* Global functions
- X***************************************************************************/
- X
- X/*
- X * SlotInit --
- X */
- XIconGrid *
- XSlotInit(dpy,screenno)
- XDisplay *dpy;
- Xint screenno;
- X{
- X IconGrid *iconGrid;
- X int occLen;
- X
- X iconGrid = MemNew(IconGrid);
- X iconGrid->iconList = NULL_LIST;
- X iconGrid->pixhoriz = DisplayWidth(dpy,screenno);
- X iconGrid->pixvert = DisplayHeight(dpy,screenno);
- X iconGrid->slotshoriz = iconGrid->pixhoriz/ICON_GRID_WIDTH;
- X iconGrid->slotsvert = iconGrid->pixvert/ICON_GRID_HEIGHT;
- X occLen = iconGrid->slotshoriz * iconGrid->slotsvert * sizeof(int);
- X iconGrid->occupancy = MemAlloc(occLen);
- X iconGrid->minoccupancy = 0;
- X
- X SlotSetLocations(dpy,iconGrid);
- X
- X return iconGrid;
- X}
- X
- X/* SlotAlloc - given a sized and possibly positioned icon window, allocate
- X * the appropriate slots for it. If the window is positioned,
- X * True should be passed for the second parameter, and the x,y
- X * position will be honoured. If the window is not positioned, it
- X * will be positioned by this function to the appropriate slots(s).
- X * If snaptogrid is true and positioned is true, the given position is
- X * modified so that the upper left corner of the icon is at the closest
- X * icon grid point. Modifies the icon structure to assign it the icon
- X * slot.
- X * Returns an IconSlot pointer if successful; NULL otherwise.
- X *
- X * If the window is not positioned, the x and y coordinates are used as
- X * offsets to the position icon; this allows particular icons to be located`
- X * in a particular logical screen within the virtual desktop.
- X */
- Xstruct _iconSlot *
- XSlotAlloc(winicon, positioned, snaptogrid)
- XWinIconFrame *winicon;
- XBool positioned;
- XBool snaptogrid;
- X{
- X int nhoriz, nvert; /* number of slots occupied, horizontally & vertically */
- X int nmajor, nminor; /* number of slots occupied, in major & minor directions */
- X IconSlot *slot;
- X IconGrid *iconGrid = winicon->core.client->scrInfo->iconGrid;
- X int scr_x, scr_y;
- X int dw, dh;
- X
- X iconGrid->iconList = ListCons(winicon, iconGrid->iconList);
- X
- X if (positioned)
- X {
- X dw = DisplayWidth(winicon->core.client->dpy,
- X winicon->core.client->screen);
- X dh = DisplayHeight(winicon->core.client->dpy,
- X winicon->core.client->screen);
- X scr_x = abs((winicon->core.x + ICON_HORZBORDER) % dw);
- X scr_y = abs((winicon->core.y + ICON_VERTBORDER) % dh);
- X slot = incrPositionedSlots(iconGrid, scr_x, scr_y,
- X winicon->core.width, winicon->core.height, snaptogrid);
- X if (winicon->core.x > 0)
- X slot->off_x = ((winicon->core.x + ICON_HORZBORDER) / dw) * dw;
- X else slot->off_x = ((winicon->core.x + ICON_HORZBORDER - dw) / dw) * dw;
- X if (winicon->core.y > 0)
- X slot->off_y = ((winicon->core.y + ICON_VERTBORDER) / dh) * dh;
- X else slot->off_y = ((winicon->core.y + ICON_VERTBORDER - dh) / dh) * dh;
- X winicon->iconslot = slot;
- X if (snaptogrid)
- X setIconPos(winicon, slot);
- X else
- X (WinFunc(winicon,core.newposfunc))(winicon,winicon->core.x,winicon->core.y);
- X }
- X else
- X {
- X nhoriz = ROUNDUP(winicon->core.width, ICON_GRID_WIDTH);
- X nvert = ROUNDUP(winicon->core.height, ICON_GRID_HEIGHT);
- X setMajorMinor(iconGrid, nvert, nhoriz, &nmajor, &nminor);
- X slot = incrDynamicSlots(iconGrid, nmajor, nminor);
- X slot->off_x = winicon->core.x + ICON_HORZBORDER;
- X slot->off_y = winicon->core.y + ICON_VERTBORDER;
- X winicon->iconslot = slot;
- X setIconPos(winicon,slot);
- X }
- X
- X return slot;
- X}
- X
- X/* SlotFree -- An icon is going away, so its references to slots should also go
- X * away. Returns True iff the free was successful.
- X * Note that if this code is changed, the similar code in SlotSetLocations
- X * may need to be changed also.
- X */
- XBool
- XSlotFree(winicon)
- XWinIconFrame *winicon;
- X{
- X List **l;
- X IconGrid *iconGrid = winicon->core.client->scrInfo->iconGrid;
- X WinIconFrame *win;
- X
- X if (winicon->iconslot == NULL)
- X {
- X return;
- X }
- X
- X incrRegion(iconGrid,winicon->iconslot,-1);
- X MemFree(winicon->iconslot);
- X winicon->iconslot = NULL;
- X
- X l = &iconGrid->iconList;
- X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
- X {
- X if (win == winicon)
- X {
- X ListDestroyCell(l);
- X break;
- X }
- X }
- X}
- X
- X/* sets the order in which slots are allocated for icons which are
- X * not explicitly positioned. The order is gotten from the global
- X * resource vector.
- X * For example, the AlongBottom order is expressed as
- X * major BottomToTop, minor LeftToRight. The major and minor orders
- X * cannot be both vertical or horizontal. Any icons which were
- X * automatically positioned are repositioned to equivalent positions
- X * in the new order.
- X */
- X/*ARGSUSED*/
- XBool
- XSlotSetLocations(dpy,iconGrid)
- XDisplay *dpy;
- XIconGrid *iconGrid;
- X{
- X List *lauto, *lpos;
- X List **l;
- X WinIconFrame *win;
- X int ima, imi;
- X
- X /* set up the new order of things */
- X switch (GRV.IconPlacement)
- X {
- X case AlongTop:
- X iconGrid->SOmajor = SOTopToBottom;
- X iconGrid->SOminor = SOLeftToRight;
- X break;
- X
- X case AlongTopRL:
- X iconGrid->SOmajor = SOTopToBottom;
- X iconGrid->SOminor = SORightToLeft;
- X break;
- X
- X case AlongBottom:
- X iconGrid->SOmajor = SOBottomToTop;
- X iconGrid->SOminor = SOLeftToRight;
- X break;
- X
- X case AlongBottomRL:
- X iconGrid->SOmajor = SOBottomToTop;
- X iconGrid->SOminor = SORightToLeft;
- X break;
- X
- X case AlongLeft:
- X iconGrid->SOmajor = SOLeftToRight;
- X iconGrid->SOminor = SOTopToBottom;
- X break;
- X
- X case AlongLeftBT:
- X iconGrid->SOmajor = SOLeftToRight;
- X iconGrid->SOminor = SOBottomToTop;
- X break;
- X
- X case AlongRight:
- X iconGrid->SOmajor = SORightToLeft;
- X iconGrid->SOminor = SOTopToBottom;
- X break;
- X
- X case AlongRightBT:
- X iconGrid->SOmajor = SORightToLeft;
- X iconGrid->SOminor = SOBottomToTop;
- X break;
- X }
- X
- X setMajorMinor(iconGrid,iconGrid->slotsvert,iconGrid->slotshoriz,
- X &(iconGrid->maslots),&(iconGrid->mislots));
- X
- X if (iconGrid->iconList == NULL_LIST)
- X {
- X for (ima = 0; ima<iconGrid->maslots; ima++)
- X for (imi = 0; imi<iconGrid->mislots; imi++)
- X OCCUPANCY(iconGrid,ima,imi)=0;
- X return;
- X }
- X
- X /* partition existing icons */
- X lauto = NULL_LIST;
- X lpos = NULL_LIST;
- X l = &iconGrid->iconList;
- X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
- X {
- X if (!win->iconslot->positioned)
- X {
- X lauto = ListCons(win,lauto);
- X }
- X else
- X {
- X lpos = ListCons(win,lpos);
- X }
- X /* this is the basics of a SlotFree */
- X MemFree(win->iconslot);
- X win->iconslot = NULL;
- X }
- X ListDestroy(iconGrid->iconList);
- X iconGrid->iconList = NULL_LIST;
- X
- X for (ima = 0; ima<iconGrid->maslots; ima++)
- X for (imi = 0; imi<iconGrid->mislots; imi++)
- X OCCUPANCY(iconGrid,ima,imi)=0;
- X
- X /* place positioned icons */
- X l = &lpos;
- X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
- X {
- X SlotAlloc(win,True,False);
- X (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
- X }
- X ListDestroy(lpos);
- X
- X /* place auto-positioned icons */
- X l = &lauto;
- X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
- X {
- X SlotAlloc(win,False,False);
- X (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
- X }
- X ListDestroy(lauto);
- X}
- END_OF_FILE
- if test 16468 -ne `wc -c <'slots.c'`; then
- echo shar: \"'slots.c'\" unpacked with wrong size!
- fi
- # end of 'slots.c'
- fi
- if test -f 'wingframe.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wingframe.c'\"
- else
- echo shar: Extracting \"'wingframe.c'\" \(15552 characters\)
- sed "s/^X//" >'wingframe.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
- X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
- X * file for terms of the license.
- X */
- X
- X/*
- X * wingframe.c -- generic frame window routines
- X */
- X
- X#ident "@(#)wingframe.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)wingframe.c 26.27 91/09/14 SMI"
- X *
- X */
- X
- X#include <errno.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <X11/Xos.h>
- X#include <X11/Xlib.h>
- X#include <X11/Xutil.h>
- X#include <X11/Xatom.h>
- X#include <X11/keysym.h>
- X#include <olgx/olgx.h>
- X
- X#include "i18n.h"
- X#include "ollocale.h"
- X#include "mem.h"
- X#include "olwm.h"
- X#include "win.h"
- X#include "globals.h"
- X#include "events.h"
- X#include "virtual.h"
- X
- X/***************************************************************************
- X* private data
- X***************************************************************************/
- X
- X/*
- X * REMIND
- X * The hadSelect variable is necessary because we sometimes receive
- X * MotionNotify events with all buttons up, even though we ask for only
- X * ButtonMotionMask. We set hadSelect only on receipt of an event that is
- X * bound to the Select action, and we ignore motion events that occur if
- X * hadSelect isn't set.
- X */
- Xstatic Bool hadSelect = False;
- Xstatic Time timeOfLastButPress = 0;
- Xstatic int buttonPressX;
- Xstatic int buttonPressY;
- Xstatic XButtonEvent lastSelectRelease;
- Xstatic XButtonEvent lastSelectPress;
- Xstatic Time lastDoubleClickTime;
- Xstatic SemanticAction currentAction = ACTION_NONE;
- X
- X/***************************************************************************
- X* forward-declared functions
- X***************************************************************************/
- X
- Xextern void ClientSetCurrent();
- X
- X/***************************************************************************
- X* static functions
- X***************************************************************************/
- X
- Xvoid
- XautoRaise(frame)
- X WinGenericFrame *frame;
- X{
- X Bool samescreen;
- X Window root, child;
- X int rootx, rooty, winx, winy;
- X unsigned int state;
- X Client *cli = frame->core.client;
- X if (cli->isFocus) {
- X if (GRV.FocusFollowsMouse) {
- X samescreen = XQueryPointer(cli->dpy, WinRootID(frame),
- X &root, &child, &rootx, &rooty, &winx, &winy, &state);
- X if (samescreen && child == frame->core.self)
- X ClientFront(cli);
- X } else {
- X ClientFront(cli);
- X }
- X }
- X}
- X
- X/***************************************************************************
- X* global functions
- X***************************************************************************/
- X
- X/*
- X * GFrameSelect -- handle selection state change
- X */
- X/*ARGSUSED*/ /* dpy arg will be used when multiple Displays supported */
- Xint
- XGFrameSelect(dpy, winInfo, selected)
- XDisplay *dpy;
- XWinGeneric *winInfo;
- XBool selected;
- X{
- X (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
- X}
- X
- X/*
- X * GFrameFocus -- handle focus changes
- X *
- X * If we're in auto-raise mode, raise the window. But if we're in focus-
- X * follows-mouse, we query the pointer to make sure we're still in the same
- X * window before we do this raise. This is to avoid restacking loops.
- X *
- X * If colormap installation is tracking the input focus, get the first entry
- X * in the client's WM_COLORMAP_WINDOWS list and install its colormap;
- X * otherwise, install the pane's colormap.
- X */
- X/*ARGSUSED*/
- Xint
- XGFrameFocus(dpy, winInfo, focus)
- XDisplay *dpy;
- XWinGenericFrame *winInfo;
- XBool focus;
- X{
- X WinGeneric *cmwi;
- X
- X if (focus) {
- X ClientSetCurrent(winInfo->core.client);
- X ClientSetWindowState(winInfo->core.client);
- X
- X if (GRV.ColorTracksInputFocus) {
- X if (winInfo->core.client->colormapWins)
- X cmwi = winInfo->core.client->colormapWins->value;
- X else
- X cmwi = (WinGeneric *) winInfo->fcore.panewin;
- X LockColormap(dpy, winInfo->core.client, cmwi);
- X }
- X
- X if (GRV.AutoRaise) {
- X if (GRV.AutoRaiseDelay > 0) {
- X TimeoutCancel();
- X TimeoutRequest(GRV.AutoRaiseDelay, autoRaise, winInfo);
- X } else {
- X autoRaise(winInfo);
- X }
- X }
- X }
- X}
- X
- X/*
- X * GFrameSetConfigFunc -- change configuration of frame window
- X * REMIND: ensure that transient windows are treated properly.
- X */
- Xint
- XGFrameSetConfigFunc(dpy, win)
- XDisplay *dpy;
- XWinGenericFrame *win;
- X{
- X XWindowChanges xwc;
- X int dw, dh;
- X Client *cli = win->core.client;
- X
- X if (win->core.dirtyconfig)
- X {
- X if (cli->sticky) {
- X dw = DisplayWidth(win->core.client->dpy,
- X win->core.client->screen);
- X dh = DisplayHeight(win->core.client->dpy,
- X win->core.client->screen);
- X
- X if (win->core.x + (int) win->core.width < 0) {
- X win->core.x = (dw + (win->core.x % dw)) % dw;
- X win->core.dirtyconfig |= CWX;
- X }
- X else if (win->core.x >= dw) {
- X win->core.x = win->core.x % dw;
- X win->core.dirtyconfig |= CWX;
- X }
- X if (win->core.y + (int) win->core.height < 0) {
- X win->core.y = (dh + (win->core.y % dh)) % dh;
- X win->core.dirtyconfig |= CWY;
- X }
- X else if (win->core.y >= dh) {
- X win->core.y = win->core.y % dh;
- X win->core.dirtyconfig |= CWY;
- X }
- X }
- X xwc.x = win->core.x;
- X xwc.y = win->core.y;
- X xwc.width = win->core.width;
- X xwc.height = win->core.height;
- X xwc.sibling = win->core.stack_sib;
- X xwc.stack_mode = win->core.stack_mode;
- X if ((win->core.dirtyconfig & CWSibling) &&
- X !(win->core.dirtyconfig &CWStackMode))
- X win->core.dirtyconfig &= ~CWSibling;
- X
- X ConfigureWindow(dpy,win,win->core.dirtyconfig,&xwc);
- X win->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode);
- X }
- X}
- X
- X/* GFrameSetStack -- set the frame's stacking position. Does not initiate
- X * a configuration change.
- X */
- Xvoid
- XGFrameSetStack(win, mask, mode, sib)
- XWinGenericFrame *win;
- Xint mask;
- Xint mode;
- XWindow sib;
- X{
- X WinGeneric *wsib;
- X
- X if ((mask & CWSibling) && (mask & CWStackMode))
- X {
- X wsib = WIGetInfo(sib);
- X if (wsib != NULL)
- X {
- X win->core.stack_sib = wsib->core.client->framewin->core.self;
- X win->core.dirtyconfig |= CWSibling;
- X }
- X }
- X if (mask & CWStackMode)
- X {
- X win->core.stack_mode = mode;
- X win->core.dirtyconfig |= CWStackMode;
- X }
- X}
- X
- X/* GFrameSetConfig - set the frame's size and position -- generally used in
- X * resizing or moving the window. We position the frame and resize the pane.
- X * If the pane has refused resizing we skip that part.
- X */
- Xvoid
- XGFrameSetConfig(win,x,y,w,h)
- XWinGenericFrame *win;
- Xint x,y,w,h;
- X{
- X WinPane *pane = (WinPane *)win->fcore.panewin;
- X
- X (WinFunc(win,core.newposfunc))(win,x,y);
- X if (pane != NULL)
- X {
- X if (WinFunc(pane,pcore.setsizefunc) != NULL)
- X (WinFunc(pane,pcore.setsizefunc))(pane,
- X w-(WinFunc(win,fcore.widthleft))(win)-(WinFunc(win,fcore.widthright))(win),
- X h-(WinFunc(win,fcore.heighttop))(win)-(WinFunc(win,fcore.heightbottom))(win));
- X WinCallConfig(win->core.client->dpy, pane, NULL);
- X }
- X else
- X {
- X WinCallConfig(win->core.client->dpy, win, NULL);
- X }
- X}
- X
- X
- X/***************************************************************************
- X* global event functions
- X***************************************************************************/
- X
- X/*
- X * GFrameEventButtonRelease -- a button has been released
- X *
- X */
- Xint
- XGFrameEventButtonRelease(dpy, event, frameInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinGenericFrame *frameInfo;
- X{
- X WinGenericPane *winPane = (WinGenericPane*)frameInfo->fcore.panewin;
- X Client *cli = frameInfo->core.client;
- X
- X if (!AllButtonsUp(event))
- X return;
- X
- X#define bevent (event->xbutton)
- X
- X switch (currentAction)
- X {
- X case ACTION_SELECT:
- X if (GRV.SelectWindows) {
- X ClearSelections(dpy);
- X AddSelection(cli, event->xbutton.time);
- X }
- X
- X ClientSetCurrent(cli);
- X ClientFront(cli);
- X
- X hadSelect = False;
- X
- X if (WinFunc(frameInfo,fcore.selectClick) != NULL)
- X {
- X (WinFunc(frameInfo,fcore.selectClick))(dpy,event,frameInfo);
- X }
- X
- X /* If the click happened in the decoration windows,
- X * (i.e. not in the pane), check for a double click.
- X * Check last click time to see if we are in double
- X * click land. Also check that the user hasn't just
- X * hit the button 3 times very rapidly. This would
- X * cause a cycle of the window changing size.
- X * REMIND this is more nasty than it should be because
- X * not all frames are yet required to have panes.
- X * Once all panes have frames the subwindow test gets
- X * easier.
- X */
- X if ((WinFunc(frameInfo,fcore.selectDoubleClick) != NULL) &&
- X ((winPane == NULL) || (bevent.subwindow != winPane->core.self)) &&
- X ((bevent.time-lastSelectRelease.time) <= GRV.DoubleClickTime) &&
- X ((bevent.time-lastDoubleClickTime) > GRV.DoubleClickTime))
- X {
- X /* we have a double click */
- X if (WinFunc(frameInfo,fcore.selectDoubleClick) != NULL)
- X {
- X (WinFunc(frameInfo,fcore.selectDoubleClick))(dpy,event,frameInfo);
- X }
- X
- X lastDoubleClickTime = bevent.time;
- X }
- X lastSelectRelease = event->xbutton;
- X currentAction = ACTION_NONE;
- X break; /* out of ACTION_SELECT case */
- X case ACTION_ADJUST:
- X if (WinFunc(frameInfo,fcore.adjustClick) != NULL)
- X {
- X (WinFunc(frameInfo,fcore.adjustClick))(dpy,event,frameInfo);
- X }
- X currentAction = ACTION_NONE;
- X break;
- X
- X }
- X}
- X
- X/*
- X * GFrameEventMotionNotify -- a button is down and the pointer is moving
- X */
- Xint
- XGFrameEventMotionNotify(dpy, event, frameInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinGenericFrame *frameInfo;
- X{
- X /* We get this only after a Select press */
- X if (hadSelect == False) /* watch for erroneous motions */
- X {
- X return;
- X }
- X
- X if (!event->xmotion.same_screen)
- X return;
- X
- X /* See if we have moved more than the threshold amount. */
- X if ((ABS(event->xmotion.x - buttonPressX) < GRV.MoveThreshold) &&
- X (ABS(event->xmotion.y - buttonPressY) < GRV.MoveThreshold))
- X return;
- X
- X (WinFunc(frameInfo,fcore.selectDrag))(dpy, event, frameInfo, &lastSelectPress);
- X
- X /*
- X * UserMoveWindows() will grab the pointer and handle events
- X * using an interposer, so we can clear the hadSelect flag.
- X */
- X hadSelect = False;
- X}
- X
- X/*
- X * GFrameEventButtonPress -- a mouse button has gone down.
- X */
- Xint
- XGFrameEventButtonPress(dpy, event, frameInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinGenericFrame *frameInfo;
- X{
- X WinPane *winPane = (WinPane*)frameInfo->fcore.panewin;
- X Window panewindow = winPane->core.self;
- X SemanticAction a;
- X unsigned int ignoremask;
- X
- X ignoremask = ModMaskMap[MOD_CONSTRAIN] |
- X ModMaskMap[MOD_INVERT] |
- X ModMaskMap[MOD_REDUCE];
- X
- X a = ResolveMouseBinding(dpy, event, ignoremask);
- X
- X switch (a) {
- X case ACTION_SELECT:
- X currentAction = a;
- X /*
- X * Save the location where the button went down so we
- X * can see if the user moves the mouse more than
- X * GRV.MoveThreshold, and wants to move the window.
- X */
- X buttonPressX = event->xbutton.x;
- X buttonPressY = event->xbutton.y;
- X
- X if (!GRV.FocusFollowsMouse &&
- X (WinFunc(frameInfo,fcore.selectPress) != NULL))
- X {
- X /* It is possible for us to replay the event and
- X * have the window, (decoration window, e.g. the
- X * resize corner, the titlebar), in which the
- X * button press happened to ignore it.
- X * In this case we would get the event
- X * again. For example, the user could button press
- X * in the title bar, (which doesn't select this event),
- X * and have this EventFrame routine get the same event
- X * twice. So, we check that the time stamp of this
- X * button press is different than the last.
- X */
- X if (event->xbutton.time == timeOfLastButPress)
- X /* We already dealt with this event. */
- X break;
- X timeOfLastButPress = event->xbutton.time;
- X if (event->xbutton.subwindow == panewindow)
- X {
- X (WinFunc(frameInfo,fcore.selectPress))(dpy,event,frameInfo);
- X }
- X
- X /* Let the button press through
- X * if we had grabbed it.
- X */
- X XAllowEvents(dpy, ReplayPointer, CurrentTime);
- X } /* End if not GRV.FocusFollowsMouse */
- X
- X lastSelectPress = event->xbutton;
- X hadSelect = True;
- X break; /* Break case ACTION_SELECT */
- X
- X case ACTION_ADJUST:
- X currentAction = a;
- X if (!GRV.FocusFollowsMouse) {
- X if (event->xbutton.time == timeOfLastButPress)
- X break;
- X timeOfLastButPress = event->xbutton.time;
- X if (event->xbutton.subwindow == panewindow
- X && WinFunc(frameInfo,fcore.adjustPress) != NULL) {
- X (WinFunc(frameInfo,fcore.adjustPress))
- X (dpy,event,frameInfo);
- X }
- X XAllowEvents(dpy, ReplayPointer, CurrentTime);
- X }
- X break;
- X case ACTION_MENU:
- X currentAction = a;
- X if (WinFunc(frameInfo,fcore.menuPress) != NULL)
- X (WinFunc(frameInfo,fcore.menuPress))(dpy, event, frameInfo);
- X break;
- X
- X } /* End switch on button pressed */
- X}
- X
- X
- X/*
- X * GFrameEventEnterNotify
- X *
- X * If we entered from outside and we're in follows-mouse mode, set the focus.
- X * If we enter the frame from the pane or directly from elsewhere (i.e.
- X * nonlinearly) install the appropriate colormap.
- X */
- Xint
- XGFrameEventEnterNotify(dpy, event, frameInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinGenericFrame *frameInfo;
- X{
- X Client *cli = frameInfo->core.client;
- X
- X if (GRV.FocusFollowsMouse && event->xcrossing.detail != NotifyInferior)
- X ClientSetFocus(cli,True,event->xcrossing.time);
- X
- X switch (event->xcrossing.detail) {
- X case NotifyInferior:
- X case NotifyNonlinear:
- X ColorWindowCrossing(dpy, event, cli->scrInfo->rootwin);
- X break;
- X }
- X}
- X
- X
- X/*
- X * GFrameEventFocus
- X *
- X * If the focus changed normally (i.e. not as the result of a keyboard grab or
- X * ungrab), call the focus functions.
- X */
- Xint
- XGFrameEventFocus(dpy, event, frameInfo)
- X Display *dpy;
- X XEvent *event;
- X WinGenericFrame *frameInfo;
- X{
- X switch (event->xfocus.mode) {
- X case NotifyNormal:
- X case NotifyWhileGrabbed:
- X if (event->xfocus.detail <= NotifyNonlinearVirtual) {
- X if (event->type == FocusIn)
- X WinCallFocus(frameInfo, True);
- X else {
- X Client *cli;
- X
- X cli = frameInfo->core.client;
- X /*
- X * When we lose focus,
- X * we have to WinCallFocus on both the Icon and the regular
- X * Frame: if we double click on an icon, it gets input
- X * focus and when it loses it, it must redraw the frame.
- X * Otherwise, the newly opened frame gets drawn as if it
- X * had input focus
- X *
- X * We can't do this when getting focus, since it confuses
- X * autoraise. There's got to be a better way . . .
- X */
- X if (cli->framewin)
- X WinCallFocus(cli->framewin, False);
- X if (cli->iconwin)
- X WinCallFocus(cli->iconwin, False);
- X }
- X }
- X break;
- X }
- X}
- END_OF_FILE
- if test 15552 -ne `wc -c <'wingframe.c'`; then
- echo shar: \"'wingframe.c'\" unpacked with wrong size!
- fi
- # end of 'wingframe.c'
- fi
- echo shar: End of archive 16 \(of 21\).
- cp /dev/null ark16isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 21 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Molecular Simulations, Inc. mail: dcmartin@postgres.berkeley.edu
- 796 N. Pastoria Avenue uucp: uwvax!ucbvax!dcmartin
- Sunnyvale, California 94086 at&t: 408/522-9236
-